package com.vhall.component.plugin.common.utils;

import org.apache.thrift.TBase;
import org.apache.thrift.TDeserializer;
import org.apache.thrift.TException;
import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TCompactProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;

/**
 * thrift 序列化工具（压缩协议）
 *
 * @author yuanzh
 */
public class ThriftCompactSerializerUtil {

    private static final Logger logger = LoggerFactory.getLogger(ThriftCompactSerializerUtil.class);

    private final TSerializer tSerializer;
    private final TDeserializer tDeserializer;
    private final ReentrantLock sLock;
    private final ReentrantLock dLock;

    private ThriftCompactSerializerUtil() {
        final TCompactProtocol.Factory factory = new TCompactProtocol.Factory();
        tSerializer = new TSerializer(factory);
        tDeserializer = new TDeserializer(factory);
        sLock = new ReentrantLock();
        dLock = new ReentrantLock();
    }

    public byte[] serializer(TBase base) throws TException {
        byte[] data = null;
        if (Objects.nonNull(base)) {
            sLock.lock();
            try {
                data = tSerializer.serialize(base);
            } catch (TException e) {
                logger.error("serializer exception, " + base, e);
                throw e;
            } finally {
                sLock.unlock();
            }
        }
        return data;
    }

    public void deserializer(TBase base, byte[] bytes) throws TException {
        if (Objects.nonNull(base) && Objects.nonNull(bytes)) {
            dLock.lock();
            try {
                tDeserializer.deserialize(base, bytes);
            } catch (TException e) {
                logger.error("deserializer exception", e);
                throw e;
            } finally {
                dLock.unlock();
            }
        }
    }

    private static final ThriftCompactSerializerUtil INSTANCE = new ThriftCompactSerializerUtil();

    public static ThriftCompactSerializerUtil getInstance() {
        return INSTANCE;
    }

}
